﻿namespace NetFx.MSIL
{
  using System;
  using System.Text;
  using System.Threading;
  using System.Collections;

  using System.Reflection;
  using System.Reflection.Emit;

  public class EventGenerator : AnyGenerator
  {
    #region Statics
    public static EventGenerator of(string name, EventAttributes attributes, Type eventType, EventBuilder builder)
    {
      return new EventGenerator(name, attributes, eventType, builder);
    }
    #endregion
    #region Fields
    /// <summary>
    /// EventBuilder is not derived from EventInfo
    /// </summary>
    protected EventBuilder builder;
    protected Type eventType;
    protected string name;
    protected EventAttributes attributes;
    protected MethodBuilder addonMethod;
    protected MethodBuilder removeonMethod;
    protected MethodBuilder raiseMethod;
    protected ArrayList methods = new ArrayList();
    #endregion
    #region Properties
    public override object AnyBuilder
    {
      get { return this.builder; }
    }
    public override DefType GeneratorType
    {
      get
      {
        return DefType.Event;
      }
    }
    public virtual Type EventType
    {
      get
      {
        return this.eventType;
      }
    }
    public virtual EventAttributes Attributes
    {
      get
      {
        return this.attributes;
      }
    }
    public virtual IList Methods
    {
      get
      {
        return this.methods;
      }
    }
    public virtual MethodBuilder AddonMethod
    {
      get
      {
        return this.addonMethod;
      }
      set
      {
        this.SetAddOnMethod(value);
      }
    }
    public virtual MethodBuilder RemoveonMethod
    {
      get
      {
        return this.removeonMethod;
      }
      set
      {
        this.SetRemoveOnMethod(value);
      }
    }
    public virtual MethodBuilder RaiseMethod
    {
      get
      {
        return this.raiseMethod;
      }
      set
      {
        this.SetRaiseMethod(value);
      }
    }
    public virtual EventToken EventToken
    {
      get
      {
        return this.Builder.GetEventToken();
      }
    }
    public virtual EventBuilder Builder
    {
      get
      {
        return this.builder;
      }
    }
    #endregion
    #region Constructors
    public EventGenerator(string name,EventAttributes attributes,Type eventType,EventBuilder builder)
    {
      if (builder == null) throw new ArgumentNullException("builder can not be null!");
      if (name == null) throw new ArgumentNullException("name can not be null!");
      if (eventType == null) throw new ArgumentNullException("eventType can not be null!");
      this.name = name;
      this.builder = builder;
      this.eventType = eventType;
      this.attributes = attributes;
    }
    #endregion
    #region Methods
    public virtual MethodInfo AddMethod(MethodBuilder method)
    {
      this.methods.Add(method);
      this.Builder.AddOtherMethod(method);

      return method;
    }
    public virtual MethodInfo SetAddOnMethod(MethodBuilder method)
    {
      this.Builder.SetAddOnMethod(this.addonMethod=method);

      return method;
    }
    public virtual MethodInfo SetRaiseMethod(MethodBuilder method)
    {
      this.Builder.SetRaiseMethod(this.raiseMethod=method);

      return method;
    }
    public virtual MethodInfo SetRemoveOnMethod(MethodBuilder method)
    {
      this.Builder.SetRemoveOnMethod(this.removeonMethod=method);

      return method;
    }
    #endregion
    #region Utils
    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        this.builder = null;
        this.name = null;
        this.eventType = null;
        this.addonMethod = null;
        this.removeonMethod = null;
        this.raiseMethod = null;
      }
      base.Dispose(disposing);
    }
    protected override void DisposeCollection(bool disposing)
    {
      if (disposing)
      {
        this.DisposeCollection(this.methods);
      }
      base.DisposeCollection(disposing);
    }
    #endregion
  }
}